<?php
namespace App\Common\Lib\Swoole\Coroutine\Batch;

use App\Common as com;
use App\Common\Lib\Swoole\Coroutine\Batch\Take as nameTake;
use App\Common\Lib\Swoole\Coroutine as nameCoroutine;

class _Take extends com\Lib\LibBase {

	/**
	 * pool对象
	 * @var nameCoroutine\Batch|null
	 */
	private ?nameCoroutine\Batch $pool = null;

	/**
	 * 任务id
	 * @var int
	 */
	private int $takeId = 0;

	/**
	 * 任务闭包
	 * @var \Closure|null
	 */
	private ?\Closure $fn = null;

	/**
	 * 已重试次数
	 * @var int
	 */
	private int $retryNumIng = 0;

	/**
	 * 最大重试次数
	 * @var int
	 */
	private int $retryNum = 0;

	/**
	 * _Take constructor.
	 * @param nameCoroutine\Batch $pool
	 * @param int $takeId
	 * @param \Closure $fn
	 */
	public function __construct( nameCoroutine\Batch $pool, int $takeId, \Closure $fn ) {
		$this->pool = $pool;
		$this->takeId = $takeId;
		$this->fn = $fn;
		//
		parent::__construct();
	}

	/**
	 * 获取takeid
	 * @return int
	 */
	public function getTakeId(  ):int {
		return $this->takeId;
	}

	/**
	 * 运行take
	 * @return mixed 执行结果
	 */
	public function run(  ):mixed {
		$this->retryNumIng = 0;
		return $this->_run();
	}

	private function _run(  ):mixed {
		try {
			return call_user_func( $this->fn, $this );
		}catch( \Exception $e ){
			// 重试
			if( $this->retryNum !== -1 ){
				if( $this->retryNumIng >= $this->retryNum ){
					return false;
				}
			}
			//
			$this->retryNumIng++;
			//
			return $this->_run();
		}
	}

	/**
	 * 克隆一个参数相同的take
	 */
	public function clone():self {
		$take = $this->pool->addTake( $this->fn );
		$take->setRetry( $this->retryNum );
		return $take;
	}

	/**
	 * 克隆多个参数相同的take
	 * @param int $cloneNum 克隆数量
	 * @return $this[]
	 */
	public function clones( int $cloneNum = 1 ):array {
		$takes = [];
		for( $i = 0; $i < $cloneNum; $i++ ){
			$takes[] = $this->clone();
		}
		//
		return $takes;
	}

	/**
	 * 最大重试次数
	 * @param int $retryNum [-1]无限 [0]不重试 [>0]重试次数
	 * @return $this
	 */
	public function setRetry( int $retryNum ):self {
		$this->retryNum = $retryNum;
		return $this;
	}

	// public function stop(  ) {}

	// public function exit(  ) {}

	// public function getStatus(  ) {}

	/**
	 * 中断检测（停止）
	 */
	// public function triggerIRQ(  ) {}

}
